1. 前言
最近工作中需要使用到WebService接口,个人比较喜欢Restful的接口风格,对WebService不是很了解。
Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是:通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。
而对于我们移动开发人员而言,它就是一种数据交互的通道。我们需要了解他的请求结构体和响应结构体。
2. WebService调试工具SoapUI
SoapUI是一个开源测试工具,通过soap/http来检查、调用、实现Web Service的功能/负载/符合性测试。该工具既可作为一个单独的测试软件使用,也可利用插件集成到Eclipse,maven2.X,Netbeans 和intellij中使用。SoapUI Pro是SoapUI的商业非开源版本,实现的功能较开源的SoapUI更多。
(找不到资源的可以在文章下方留言)
3. 接口分析(以getMobileCodeInfo为例)
以 http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl 为测试例子
从上面两个图可以看到我们得请求体和响应体的结构和内容,以XML格式作为数据交互的结构类型。
4. 程序设计
4.1 添加依赖
1 2 3 4 5 6 7 8 9
| implementation 'com.squareup.okhttp3:okhttp:3.8.0' implementation 'com.parkingwang:okhttp3-loginterceptor:0.5' implementation 'com.squareup.retrofit2:retrofit:2.3.0' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' implementation('com.squareup.retrofit2:converter-simplexml:2.3.0') { exclude module: 'stax' exclude module: 'stax-api' exclude module: 'xpp3' }
|
4.2 请求体设计
从请求体XML结构而言
1 2 3 4 5 6 7 8 9 10 11
| <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://WebXml.com.cn/"> <soap:Header/> <soap:Body> <web:getMobileCodeInfo>
<web:mobileCode>18507152743</web:mobileCode> </web:getMobileCodeInfo> </soap:Body> </soap:Envelope>
|
最外层soap:Envelope
其次soap:Body
最后web:getMobileCodeInfo,而web:getMobileCodeInfo中有一个mobileCode我们可以用变量表示,所以创建如下三个类:
MobileCodeRequestEnvelope.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Root(name = "soap:Envelope") @NamespaceList({ @Namespace(prefix = "xsi", reference = "http://www.w3.org/2001/XMLSchema-instance"), @Namespace(prefix = "xsd", reference = "http://www.w3.org/2001/XMLSchema"), @Namespace(prefix = "soap", reference = "http://www.w3.org/2003/05/soap-envelope") }) public class MobileCodeRequestEnvelope {
@Element(name = "soap:Body", required = false) private MobileCodeRequestBody body;
public MobileCodeRequestBody getBody() { return body; }
public void setBody(MobileCodeRequestBody body) { this.body = body; } }
|
MobileCodeRequestBody.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Root(name = "soap:Body", strict = false) public class MobileCodeRequestBody { @Element(name = "getMobileCodeInfo", required = false) private MobileCodeRequestData mMobileCodeRequestData;
public MobileCodeRequestData getMobileCodeRequestData() { return mMobileCodeRequestData; }
public void setMobileCodeRequestData( MobileCodeRequestData mobileCodeRequestData) { mMobileCodeRequestData = mobileCodeRequestData; } }
|
MobileCodeRequestData.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Root(name = "getMobileCodeInfo", strict = false) @Namespace(reference = "http://WebXml.com.cn/") public class MobileCodeRequestData { @Element(name = "mobileCode", required = false) private String mobileCode;
public String getMobileCode() { return mobileCode; }
public void setMobileCode(String mobileCode) { this.mobileCode = mobileCode; } }
|
4.3 响应体设计
从响应体XML而言
1 2 3 4 5 6 7
| <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <getMobileCodeInfoResponse xmlns="http://WebXml.com.cn/"> <getMobileCodeInfoResult>18507152743:湖北 武汉 湖北联通GSM卡</getMobileCodeInfoResult> </getMobileCodeInfoResponse> </soap:Body> </soap:Envelope>
|
最外层soap:Envelope
其次soap:Body
然后getMobileCodeInfoResponse,最后getMobileCodeInfoResult,我们可以用变量表示,所以创建如下三个类:
MobileCodeResponseEnvelope.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Root(name = "soap:Envelope") @NamespaceList({ @Namespace( prefix = "xsi", reference = "http://www.w3.org/2001/XMLSchema-instance"), @Namespace( prefix = "xsd", reference = "http://www.w3.org/2001/XMLSchema"), @Namespace( prefix = "soap", reference = "http://www.w3.org/2003/05/soap-envelope") }) public class MobileCodeResponseEnvelope { @Element(name = "Body", required = false) private MobileCodeResponseBody mMobildCodeResponseBody;
public MobileCodeResponseBody getMobildCodeResponseBody() { return mMobildCodeResponseBody; }
public void setMobildCodeResponseBody( MobileCodeResponseBody mobildCodeResponseBody) { mMobildCodeResponseBody = mobildCodeResponseBody; } }
|
MobileCodeResponseBody.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Root(name = "Body") public class MobileCodeResponseBody { public MobileCodeResponseInfo getMobileCodeResponseInfo() { return mMobileCodeResponseInfo; }
public void setMobileCodeResponseInfo( MobileCodeResponseInfo mobileCodeResponseInfo) { mMobileCodeResponseInfo = mobileCodeResponseInfo; }
@Element(name = "getMobileCodeInfoResponse", required = false) private MobileCodeResponseInfo mMobileCodeResponseInfo; }
|
MobileCodeResponseInfo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Root(name = "getMobileCodeInfoResponse",strict = false) public class MobileCodeResponseInfo {
public String getMobileCodeResult() { return MobileCodeResult; }
public void setMobileCodeResult(String mobileCodeResult) { MobileCodeResult = mobileCodeResult; }
@Element(name = "getMobileCodeInfoResult", required = false) private String MobileCodeResult; }
|
4.4 接口设计
1 2 3 4 5 6 7 8 9
| public interface mobileCodeApi { @Headers({ "Content-Type: text/xml", "Accept-Charset: utf-8" }) @POST("MobileCodeWS.asmx") Call<MobileCodeResponseEnvelope> getMobileCodeInfo( @Body MobileCodeRequestEnvelope requestEnvelope); }
|
4.5 Retrofit创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class Retrofitance { private static Strategy strategy = new AnnotationStrategy(); private static Serializer serializer = new Persister(strategy);
private static OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
private static Retrofit.Builder retrofitBuilder = new Retrofit.Builder() .addConverterFactory(SimpleXmlConverterFactory.create(serializer)) .baseUrl(Constant.BASE_URL);
public static <T> T createMobileCodeService(Class<T> serviceClass) { okHttpClient.interceptors().add(new Interceptor() { @Override public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException { Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder() .header("Content-Type", "text/xml;charset=UTF-8") .method(original.method(), original.body());
Request request = requestBuilder.build(); return chain.proceed(request); } });
OkHttpClient client = okHttpClient.connectTimeout(1, TimeUnit.MINUTES) .addInterceptor(new LogInterceptor()) .writeTimeout(1, TimeUnit.MINUTES) .readTimeout(1, TimeUnit.MINUTES) .build(); Retrofit retrofit = retrofitBuilder.client(client).build(); return retrofit.create(serviceClass); } }
|
4.6 请求数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| mobileCodeApi apiService = Retrofitance.createMobileCodeService(mobileCodeApi.class); MobileCodeRequestEnvelope requestEnvelope = new MobileCodeRequestEnvelope(); MobileCodeRequestBody requestBody = new MobileCodeRequestBody(); MobileCodeRequestData requestData = new MobileCodeRequestData();
requestData.setMobileCode("18507152743"); requestBody.setMobileCodeRequestData(requestData); requestEnvelope.setBody(requestBody);
Call<MobileCodeResponseEnvelope> call = apiService.getMobileCodeInfo(requestEnvelope); call.enqueue(new Callback<MobileCodeResponseEnvelope>() { @Override public void onResponse(Call<MobileCodeResponseEnvelope> call, Response<MobileCodeResponseEnvelope> response) { MobileCodeResponseEnvelope mobileCodeResponseEnvelope = response.body(); if (mobileCodeResponseEnvelope != null) { Toast.makeText(MainActivity.this, "请求成功", Toast.LENGTH_SHORT).show(); String result = mobileCodeResponseEnvelope.getMobildCodeResponseBody() .getMobileCodeResponseInfo().getMobileCodeResult(); mTvMobileResult.setText(result); System.err.println("yidong -- result = " + result); } }
@Override public void onFailure(Call<MobileCodeResponseEnvelope> call, Throwable t) { System.err.println("yidong -- onFailure"); Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show(); } });
|
4.7 效果
5. 源码地址
RetrofitWebService